//
// Created by jyh on 2021/7/30.
//
#include "Com.h"

// STRING
char *trim(char *str){
    char *p = str;
    char *p1;
    if(p)
    {
        p1 = p + strlen(str) - 1;
        while(*p && isspace(*p)) p++;
        while(p1 > p && isspace(*p1)) *p1-- = '/0';
    }
    return p;
}
int len_trim(const char* pStr) {
    int length = strlen(pStr);
    int count = length;
    int i;
    for (i = length - 1; i >= 0; i--)
    {
        if (pStr[i] == '\0' || pStr[i] == '\n' || pStr[i] == '\r'
            || pStr[i] == ' ')
            count--;
        else
            break;
    }
    return count;
}
char* substringEx(char* dest, const char* src, int start, int length) {
    int i, j = 0;
    int len = strlen(src);
    if (start < 0 || start >= len || start + length > len)
    {
        dest[0] = '\0';
        return NULL;
    }
    for (i = start; i < start + length; i++)
    {
        dest[j] = src[i];
        j++;
    }
    dest[j] = '\0';
    return dest;
}
char* left_justify_string(char* string) {
    int p = 0;
    while (*(string + p) == ' ' || *(string + p) == '\n'
           || *(string + p) == '\r')
        p++;
    return string + p;
}
char* toUpper(char* value) {
    int len = strlen((const char*)value);
    int i;
    for (i = 0; i < len; i++)
    {
        if (value[i] >= 'a' && value[i] <= 'z')
            value[i] -= 32;
    }
    return value;
}
char* toLower(char* value) {
    int len = strlen((const char*)value);
    int i;
    for (i = 0; i < len; i++)
    {
        if (value[i] >= 'A' && value[i] <= 'Z')
            value[i] += 32;
    }
    return value;
}
bool isUpperLetter(unsigned char data) {
    return data >= 'A' && data <= 'Z';
}
void split_string(bool lnoempty, char* string, char c_start, char c_end, char seperator, int* nword, char* keys, int len) {
    int i0 = 0, i1, ilast, i;
    char varword[1024];
    char* word = (char*)keys;
    i1 = len_trim(string) - 1;
    if (c_start != ' ')
        i0 = index_string(string, c_start);
    if (c_end != ' ')
        i1 = index_string(string, c_end);
    *nword = 0;
    if (i1 == -1 || i0 > i1)
        return;

    ilast = i0;
    if (string[i1] != seperator)
        string[i1 + 1] = seperator;
    string[i1 + 2] = '\0';

    for (i = i0; i < i1 + 2; i++)
    {
        if (string[i] == seperator)
        {
            if (i - 1 >= ilast)
            {
                substringEx(varword, string, ilast, i - ilast);
                strcpy(word + (*nword) * len, varword);
                (*nword)++;
            }
            else
            {
                if (!lnoempty)
                {
                    strcpy(word + (*nword) * len, "  ");
                    (*nword)++;
                }
            }
            ilast = i + 1;
        }
    }
}
int pointer_string(int cnt, char *string_array[], char *str) {
    int itr, idx = -1;
    for (itr = 0;itr < cnt;itr++)
    {
        if (strcmp(string_array[itr], str)==0)
        {
            idx = itr;
            break;
        }
    }
    return idx;
}
int pointer_charstr(int row, int col, const char* string_array, const char* string) {
    int i;
    const char* pStr = (const char*)string_array;
    for (i = 0; i < row; i++)
    {
        if (strncmp(pStr + i * col, string, strlen(string)) == 0)
            break;
    }
    if (i == row)
        i = -1;
    return i;
}
int index_string(const char* src, char key) {
    int len = strlen(src);
    int i;
    for (i = 0; i < len; i++)
    {
        if (src[i] == key)
            break;
    }
    if (i == len)
        return -1;
    else
        return i;
}
char* Itoa(int src){
    int temp = -1;
    int tv = src>0?src:-src;
    int length = 0;
    while ((tv = tv/10)>0) {
        length++;
    }
    length++;
    tv = src>0?src:-src;
    char* des = (char*)malloc(sizeof(char)*(length+1));
    memset(des, 0, length+1);
    for (int i=0; i<length; i++) {
        int v = 1;
        for (int j=length-i; j>1;j--) {
            v = v*10;
        }
        temp = tv/(v);
        des[i] = (temp + 48);//accii码0对应48
        if (temp == 0) {
            temp = 1;
        }
        tv = tv%(temp*v);
    }
    des[length] = '\0';
    if (src<0) {
        char* nSrc = (char*)malloc((strlen(des)+2)*sizeof(char));
        sprintf(nSrc, "-%s",des);
        free(des);
        des = nSrc;
    }
    return des;
}

// TIME TRANS
void yr2year(int* yr) {
    if (yr > 1900)
        return;
    if (yr <= 30)
        yr += 2000;
    else
        yr += 1900;
}
int md_julday(int iyear, int imonth, int iday) {
    int iyr, result;
    int doy_of_month[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304,
                             334 };
    if (iyear < 0 || imonth < 0 || iday < 0 || imonth > 12 || iday > 366
        || (imonth != 0 && iday > 31))
    {
        printf("iyear = %d,imonth = %d,iday = %d,incorrect argument", iyear, imonth, iday);
        exit(1);
    }
    iyr = iyear;
    if (imonth <= 2)
        iyr -= 1;
    result = 365 * iyear - 678941 + iyr / 4 - iyr / 100 + iyr / 400 + iday;
    if (imonth != 0)
        result = result + doy_of_month[imonth - 1];
    return result;
}
void yeardoy2monthday(int iyear, int idoy, int* imonth, int* iday) {
    int days_in_month[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int id, i;
    if ((iyear % 4 == 0 && iyear % 100 != 0) || iyear % 400 == 0)
        days_in_month[1] = 29;
    id = idoy;
    for (i = 0; i < 12; i++)
    {
        id = id - days_in_month[i];
        if (id > 0)
            continue;
        *iday = id + days_in_month[i];
        *imonth = i + 1;
        break;
    }
}
double timdif(int jd2, double sod2, int jd1, double sod1) {
    return 86400.0 * (jd2 - jd1) + sod2 - sod1;
}
void mjd2wksow(int mjd, double sod, int* week, double* sow) {
    *week = (int)((mjd + sod / 86400.0 - 44244.0) / 7.0);
    *sow = (mjd - 44244.0 - *week * 7) * 86400.0 + sod;
}
void mjd2doy(int jd, int* iyear, int* idoy) {
    *iyear = (jd + 678940) / 365;
    *idoy = jd - md_julday(*iyear, 1, 1);
    while (*idoy <= 0)
    {
        (*iyear)--;
        *idoy = jd - md_julday(*iyear, 1, 1) + 1;
    }
}
void mjd2date(int jd, double sod, int* iyear, int* imonth, int* iday, int* ih, int* imin, double* sec) {
    int doy = 0;
    mjd2doy(jd, iyear, &doy);
    yeardoy2monthday(*iyear, doy, imonth, iday);

    *ih = (int)(sod / 3600.0);
    *imin = (int) ((sod - (*ih) * 3600.0) / 60.0);
    *sec = sod - (*ih) * 3600.0 - (*imin) * 60.0;
}
time_t mjd2time(int mjd, double sod) {
    const int doy[] = { 1,32,60,91,121,152,182,213,244,274,305,335 };
    time_t time = 0;
    int days, sec, year, mon, day, hour, min;
    double dsec;
    mjd2date(mjd, sod, &year, &mon, &day, &hour, &min, &dsec);
    if (year < 1970 || 2099 < year || mon < 1 || 12 < mon) return time;

    /* leap year if year%4==0 in 1901-2099 */
    days = (year - 1970) * 365 + (year - 1969) / 4 + doy[mon - 1] + day - 2 + (year % 4 == 0 && mon >= 3 ? 1 : 0);
    sec = (int)floor(dsec);
    time = (time_t)days * 86400 + hour * 3600 + min * 60 + sec;
    return time;
}
void time2mjd(time_t time, int* mjd, double* sod) {
    double ep[6];
    const int mday[] = { /* # of days in a month */
            31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 28, 31, 30, 31, 30, 31,
            31, 30, 31, 30, 31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
            31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    int days, sec, mon, day;

    /* leap year if year%4==0 in 1901-2099 */
    days = (int)(time / 86400);
    sec = (int)(time - (time_t)days * 86400);
    for (day = days % 1461, mon = 0; mon < 48; mon++)
    {
        if (day >= mday[mon])
            day -= mday[mon];
        else
            break;
    }
    ep[0] = 1970 + days / 1461 * 4 + mon / 12;
    ep[1] = mon % 12 + 1;
    ep[2] = day + 1;
    ep[3] = sec / 3600;
    ep[4] = sec % 3600 / 60;
    ep[5] = sec % 60;

    *mjd = md_julday((int)ep[0], (int)ep[1], (int)ep[2]);
    *sod = ep[3] * 3600.0 + ep[4] * 60.0 + ep[5];
}
void wksow2mjd(int week, double sow, int* mjd, double* sod) {
    if (mjd != NULL)
        *mjd = (int)(sow / 86400.0) + week * 7 + 44244;
    if (sod != NULL)
        *sod = fmod(sow, 86400.0);
}
void gpsweek(int year, int month, int day, int* week, int* wd) {
    int mjd;
    if (year != 0)
    {
        if (month != 0)
            mjd = md_julday(year, month, day);
        else
            mjd = md_julday(year, 1, 1) + day - 1;
    }
    else
        mjd = day;
    *week = (mjd - 44244) / 7;
    *wd = mjd - 44244 - (*week) * 7;
}
void timinc(int jd, double sec, double delt, int* jd1, double* sec1) {
    *sec1 = sec + delt;
    int inc = (int)(*sec1 / 86400.0);
    *jd1 = jd + inc;
    *sec1 = *sec1 - inc * 86400.0;
    if (*sec1 >= 0)
        return;
    *jd1 = *jd1 - 1;
    *sec1 = *sec1 + 86400;
}
void brdtime(char* cprn, int* mjd, double* sod) {
    switch (cprn[0])
    {
        case 'C':
        case 'B':
            timinc(*mjd, *sod, 14.0, mjd, sod);
            break;
        case 'R':
            timinc(*mjd, *sod, Taiutc_m_getTaiutc(*mjd) - 19.0, mjd, sod);
            break;
    }
}
int genAode(char csys, int mjd, double sod, double toe, int inade, struct GPSEPH* eph) {
    int mjd_r, ret = -1;
    double sod_r;
    if (csys == 'G' || csys == 'J')
        ret = inade;
    else if (csys == 'R')
    {
        timinc(mjd, sod, 19.0 - Taiutc_m_getTaiutc(mjd), &mjd_r, &sod_r);
        //		ret = NINT(sod / 900.0) + 1;
        //IGMAS:
        ret = NINT(fmod(sod_r + 10800.0, 86400.0) / 900.0);
    }
    else if (csys == 'E')
    {
        // ret = NINT(sod / 600.0) + 1;
        //IGMAS:
        ret = inade;
    }
    else if (csys == 'C')
    {
        //       ret = NINT(fmod(toe, 86400.0) / 1800.0) + 1; // zhbd
        //		 ret = NINT(sod / 1800.0) + 1;
        //IGMAS
        ret = NINT(fmod(toe, 86400.0) / 450.0); // geng laoshi
        //		ret = getbdsiode(*eph);
        //        ret = (int)eph->iodc;
    }
    return ret;
}

// COORDINATE TRANS
void blhxyz(double* geod, double a0, double b0, double* x) {
    double a, b, e2, N, W;
    if (a0 == 0 || b0 == 0)
    {
        a = 6378137.0;
        b = 298.257223563;  //alpha = (a-b)/a
    }
    else
    {
        a = a0;
        b = b0;
    }
    if (b <= 6000000)
        b = a - a / b;
    e2 = (a * a - b * b) / (a * a);

    W = sqrt(1 - e2 * pow(sin(geod[0]), 2));
    N = a / W;
    x[0] = (N + geod[2]) * cos(geod[0]) * cos(geod[1]);
    x[1] = (N + geod[2]) * cos(geod[0]) * sin(geod[1]);
    x[2] = (N * (1 - e2) + geod[2]) * sin(geod[0]);
}
void xyzblh(double* x, double scale, double a0, double b0, double dx, double dy,
            double dz, double* geod) {
    double a, b;
    long double xp, yp, zp, s, e2, rhd, rbd, n, zps, tmp1, tmp2;
    int i;

    if (a0 == 0 || b0 == 0)
    {
        a = 6378137.0;
        b = 298.257223563;  //alpha = (a-b)/a
    }
    else
    {
        a = a0;
        b = b0;
    }
    for (i = 0; i < 3; i++)
        geod[i] = 0;
    xp = x[0] * scale + dx;
    yp = x[1] * scale + dy;
    zp = x[2] * scale + dz;

    if (b <= 6000000)
        b = a - a / b;
    e2 = (a * a - b * b) / (a * a);
    s = sqrt(xp * xp + yp * yp);
    geod[1] = atan(yp / xp);
    if (geod[1] < 0)
    {
        if (yp > 0)
            geod[1] += PI;
        if (yp < 0)
            geod[1] += 2 * PI;
    }
    else
    {
        if (yp < 0)
            geod[1] += PI;
    }
    zps = zp / s;
    geod[2] = sqrt(xp * xp + yp * yp + zp * zp) - a;
    geod[0] = atan(zps / (1.0 - e2 * a / (a + geod[2])));
    n = 1;
    rhd = rbd = 1;
    while (rbd * n > 1e-4 || rhd > 1e-4)
    {
        n = a / sqrt(1.0 - e2 * sin(geod[0]) * sin(geod[0]));
        tmp1 = geod[0];
        tmp2 = geod[2];
        geod[2] = s / cos(geod[0]) - n;
        geod[0] = atan(zps / (1.0 - e2 * n / (n + geod[2])));
        rbd = ABS(tmp1 - geod[0]);
        rhd = ABS(tmp2 - geod[2]);
    }
}
void rot_enu2xyz(double lat, double lon, double(*rotmat)[3]) {
    double coslat, sinlat, coslon, sinlon;
    coslat = cos(lat - PI / 2);
    sinlat = sin(lat - PI / 2);
    coslon = cos(-PI / 2 - lon);
    sinlon = sin(-PI / 2 - lon);

    rotmat[0][0] = coslon;
    rotmat[0][1] = sinlon * coslat;
    rotmat[0][2] = sinlon * sinlat;
    rotmat[1][0] = -sinlon;
    rotmat[1][1] = coslon * coslat;
    rotmat[1][2] = coslon * sinlat;
    rotmat[2][0] = 0;
    rotmat[2][1] = -sinlat;
    rotmat[2][2] = coslat;
}
void matmpy(double* A, double* B, double* C, int row, int colA, int colB) {
    int i, j, k;
    double value;
    double* dest = (double*)calloc(row * colB, sizeof(double));
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < colB; j++)
        {
            value = 0;
            for (k = 0; k < colA; k++)
            {
                value += A[i * colA + k] * B[k * colB + j];
            }
            dest[i * colB + j] = value;
        }
    }
    for (i = 0;i < row;i++)
    {
        for (j = 0;j < colB;j++)
        {
            C[i * colB + j] = dest[i * colB + j];
        }
    }
    free(dest);
}
void transpose(double* in, double* out, int row, int col) {
    double* tmp = (double*)calloc(row * col, sizeof(double));
    int i, j;
    for (i = 0;i < row;i++)
        for (j = 0; j < col;j++)
            tmp[j * row + i] = in[i * col + j];

    for (j = 0; j < col;j++)
        for (i = 0;i < row;i++)
            out[j * row + i] = tmp[j * row + i];
    free(tmp);
}

// JSON
void excludeAnnoValue(char* value, const char* in) {
    int num = 0, lstart = false;
    const char* ptr = in;
    while (*ptr != '\0')
    {
        if (lstart == false && (*ptr == ' ' || *ptr == '\n' || *ptr == '\t'))
        {
            ++ptr;
            continue;
        }
        lstart = true;
        if (*ptr != '#' && *ptr != '!')
        {
            value[num++] = *ptr;
            ++ptr;
        }
        else
            break;
    }
    value[num++] = '\0';
    trim(value);
}

// BAMBOO
void getfreq(char csys, char* freq, int ifreq, double* val) {
    switch (csys)
    {
        case 'G':
            if (strstr(freq, "L1") != NULL) {*val = GPS_L1;}
            else if (strstr(freq, "L2") != NULL){*val = GPS_L2;}
            else if (strstr(freq, "L5") != NULL){*val = GPS_L5;}
            else{
                printf("freq = %s,unknow frequency for GPS", freq);
                exit(1);
            }
            break;
        case 'R':
            if (strstr(freq, "L1") != NULL) {*val = GLS_L1 + ifreq * GLS_dL1;}
            else if (strstr(freq, "L2") != NULL){*val = GLS_L2 + ifreq * GLS_dL2;}
            else{
                printf("freq = %s,unknow frequency for GLONASS", freq);
                exit(1);
            }
            break;
        case 'E':
            if (strstr(freq, "L1") != NULL) {*val = GAL_E1;}
            else if (strstr(freq, "L8") != NULL){*val = GAL_E5;}
            else if (strstr(freq, "L6") != NULL){*val = GAL_E6;}
            else if (strstr(freq, "L5") != NULL){*val = GAL_E5a;}
            else if (strstr(freq, "L7") != NULL){*val = GAL_E5b;}
            else{
                printf("freq = %s,unknow frequency for GALILEO", freq);
                exit(1);
            }
            break;
        case 'C':
            if (strstr(freq, "L1") != NULL){*val = BDS_B1c;}             
            else if (strstr(freq, "L2") != NULL){*val = BDS_B1;}
            else if (strstr(freq, "L5") != NULL){*val = BDS_B2a;}
            else if (strstr(freq, "L6") != NULL){*val = BDS_B3;}
            else if (strstr(freq, "L7") != NULL){*val = BDS_B2b;}
            else if (strstr(freq, "L8") != NULL){*val = BDS_B2;}
            else{
                printf("freq = %s,unknow frequency for BDS", freq);
                exit(1);
            }
            break;
        case 'J':
            if (strstr(freq, "L1") != NULL){*val = QZS_L1;}             
            else if (strstr(freq, "L2") != NULL){*val = QZS_L2;}
            else if (strstr(freq, "L5") != NULL){*val = QZS_L5;}
            else if (strstr(freq, "L6") != NULL){*val = QZS_LEX;}
            else{
                printf("freq = %s,unknow frequency for QZSS", freq);
                exit(1);
            }
            break;
        default:
        printf("freq = %s,unknow frequency", freq);
        exit(1);
    }
}
int index_freq(char(*cfreq)[LEN_FREQ], int nfreq, const char* freq) {
    int rfreq = -1;
    for (int ifreq = 0;ifreq < nfreq;ifreq++)
    {
        if (strstr(cfreq[ifreq], freq))
        {
            rfreq = ifreq;
            break;
        }
    }
    return rfreq;
}
void get_freq(struct Satellite* SAT, const char* type, int nfreq, char(*cfreq)[LEN_FREQ]) {
    int i, j;
    double tmp;
    char key[16];
    if (nfreq == 0)
    {
        printf("cprn = %s,nfreq = %d,frequency used for satellite is not selected!", SAT->cprn, nfreq);
        exit(1);
    }
    if (strstr(type, "IF") != NULL)
    {
        for (i = 0; i < nfreq; i++)
            getfreq(SAT->cprn[0], cfreq[i], SAT->ifreq, SAT->freq + i);
        if (nfreq < 1)
        {
            printf("nfreq = %d,mode = %s,frequency is not enough for process mode!", nfreq, type);
            exit(1);
        }
        /// Only compare the first two frequency,leave the third alone
        for (i = 0; i < nfreq; i++)
        {
            for (j = i + 1; j < nfreq; j++)
            {
                if (SAT->freq[i] < SAT->freq[j])
                {
                    tmp = SAT->freq[j];
                    SAT->freq[j] = SAT->freq[i];
                    SAT->freq[i] = tmp;

                    strcpy(key, cfreq[j]);
                    strcpy(cfreq[j], cfreq[i]);
                    strcpy(cfreq[i], key);
                }
            }
        }
        SAT->g = SAT->freq[0] / SAT->freq[1];
        SAT->g2 = SAT->g * SAT->g;
        SAT->lamdw = VEL_LIGHT / fabs(SAT->freq[0] - SAT->freq[1]);
        SAT->lamdn = VEL_LIGHT / fabs(SAT->freq[0] + SAT->freq[1]);
        SAT->fac[0] = SAT->g2 / (SAT->g2 - 1.0);
        SAT->fac[1] = 1.0 / (SAT->g2 - 1.0);
        for (i = 0; i < nfreq; i++)
            SAT->lamda[i] = VEL_LIGHT / SAT->freq[i];
    }
    else if (strstr(type, "SF") != NULL || strstr(type, "RAW") != NULL)
    {
        for (i = 0; i < nfreq; i++)
        {
            getfreq(SAT->cprn[0], cfreq[i], SAT->ifreq, SAT->freq + i);
        }
        if (nfreq > 1)
        {
            /// Only compare the first two frequency,leave the third alone
            for (i = 0; i < nfreq; i++)
            {
                for (j = i + 1; j < nfreq; j++)
                {
                    if (SAT->freq[i] < SAT->freq[j])
                    {
                        tmp = SAT->freq[j];
                        SAT->freq[j] = SAT->freq[i];
                        SAT->freq[i] = tmp;

                        strcpy(key, cfreq[j]);
                        strcpy(cfreq[j], cfreq[i]);
                        strcpy(cfreq[i], key);
                    }
                }
            }
            SAT->g = SAT->freq[0] / SAT->freq[1];
            SAT->g2 = SAT->g * SAT->g;
            SAT->lamdw = VEL_LIGHT / fabs(SAT->freq[0] - SAT->freq[1]);
            SAT->lamdn = VEL_LIGHT / fabs(SAT->freq[0] + SAT->freq[1]);
            SAT->fac[0] = SAT->g2 / (SAT->g2 - 1.0);
            SAT->fac[1] = 1 / (SAT->g2 - 1.0);
        }
        else
        {
            ;
        }
        for (i = 0; i < nfreq; i++)
        {
            SAT->lamda[i] = VEL_LIGHT / SAT->freq[i];
        }
    }
    else
    {
        printf("type = %s,unknow observation type", type);
        exit(1);
    }
}
double freqbytp(int isat, const char* freq) {
    switch (DLY.cprn[isat][0])
    {
        case 'G':
            if (strstr(freq, "L1") != NULL) {return GPS_L1;}
            else if (strstr(freq, "L2") != NULL) {return GPS_L2;}
            else if (strstr(freq, "L5") != NULL) {return GPS_L5;}
            else{ printf("freq = %s,unknow frequency for GPS", freq); exit(1);}
            break;
        case 'C':
            if (strstr(freq, "L1") != NULL) {return BDS_B1c;}
            else if (strstr(freq, "L2") != NULL) {return BDS_B1;}
            else if (strstr(freq, "L7") != NULL) {return BDS_B2b;}
            else if (strstr(freq, "L6") != NULL) {return BDS_B3;}
            else if (strstr(freq, "L5") != NULL) {return BDS_B2a;}
            else if (strstr(freq, "L8") != NULL) {return BDS_B2;}
            else{ printf("freq = %s,unknow frequency for BDS", freq); exit(1);}
            break;
        case 'R':
            if (strstr(freq, "L1") != NULL) {return GLS_L1 + DLY.SAT[isat].ifreq * GLS_dL1;}
            else if (strstr(freq, "L2") != NULL) {return GLS_L2 + DLY.SAT[isat].ifreq * GLS_dL2;}
            else{ printf("freq = %s,unknow frequency for GLONASS", freq); exit(1);}
            break;
        case 'E':
            if (strstr(freq, "L1") != NULL) {return GAL_E1;}
            else if (strstr(freq, "L8") != NULL) {return GAL_E5;}
            else if (strstr(freq, "L6") != NULL) {return GAL_E6;}
            else if (strstr(freq, "L5") != NULL) {return GAL_E5a;}
            else if (strstr(freq, "L7") != NULL) {return GAL_E5b;}
            else{ printf("freq = %s,unknow frequency for GALILEO", freq); exit(1);}
            break;
        case 'J':
            if (strstr(freq, "L1") != NULL) {return QZS_L1;}
            else if (strstr(freq, "L2") != NULL) {return QZS_L2;}
            else if (strstr(freq, "L5") != NULL) {return QZS_L5;}
            else if (strstr(freq, "L6") != NULL) {return QZS_LEX;}
            else{ printf("freq = %s,unknow frequency for QZSS", freq); exit(1);}
            break;
        default:
            printf("type = %s,unknow observation type", DLY.cprn[isat]);
            break;
    }
    return 0;
}
void updateSatfreq(struct Satellite* sat) {
    int isys = index_string(SYS, sat->cprn[0]);
    int isat = pointer_string(DLY.nprn, DLY.cprn, sat->cprn);
    char* tmpstr=calloc(257,sizeof(char));
    // lambda for each frequency
    for (int ifreq = 0; ifreq < DLY.nfreq_obs[isys] && -1 != isat;++ifreq)
    {
        double fq = freqbytp(isat, DLY.freq_obs[isys][ifreq]);
        strcpy(sat->mlam[ifreq].key, DLY.freq_obs[isys][ifreq]);
        sat->mlam[ifreq].val=VEL_LIGHT / fq;
        //sat->mlam[DLY.freq_obs[isys][ifreq]] = VEL_LIGHT / fq;
    }
    // lamdw for each combination
    for (int ifreq = 0;ifreq < DLY.nfreq_obs[isys];++ifreq)
    {
        double fq1 = VEL_LIGHT / sat->mlam[Map_index(sat->mlam,DLY.freq_obs[isys][ifreq],MAXFREQ)].val;
        //double fq1 = VEL_LIGHT / sat->mlam[DLY.freq_obs[isys][ifreq]];
        for (int jfreq = ifreq + 1;jfreq < DLY.nfreq_obs[isys];++jfreq)
        {
            double fq2 = VEL_LIGHT / sat->mlam[Map_index(sat->mlam,DLY.freq_obs[isys][jfreq],MAXFREQ)].val;
            //double fq2 = VEL_LIGHT / sat->mlam[DLY.freq_obs[isys][jfreq]];
            double lamw = VEL_LIGHT / (fq1 - fq2);
            strcpy(tmpstr,DLY.freq_obs[isys][ifreq]); strcat(tmpstr,"_"); strcat(tmpstr,DLY.freq_obs[isys][jfreq]);
            strcpy(sat->mlamw[ifreq].key, tmpstr);
            sat->mlamw[Map_index(sat->mlamw,tmpstr,MAXFREQ)].val = lamw;
            memset(tmpstr,0,sizeof(char)*strlen(tmpstr));
            //sat->mlamw[string(DLY.freq_obs[isys][ifreq]) + "_" + string(DLY.freq_obs[isys][jfreq])] = lamw;
        }
    }
    free(tmpstr);
}
double dot(int n, double* v1, double* v2) {
    int i;
    double res;
    res = 0.0;
    for (i = 0; i < n; i++)
        res = res + v1[i] * v2[i];
    return res;
}
double distance(int n, double* v1, double* v2) {
    int i;
    double* dx = (double*)calloc(n, sizeof(double)), dist;
    for (i = 0; i < n;i++)
        dx[i] = v1[i] - v2[i];
    dist = sqrt(dot(n, dx, dx));
    free(dx);
    return dist;
}
bool exsitobs(double obs[2*MAXFREQ]){
    double sum=0;
    for(int i=0; i<MAXFREQ; i++){
        sum+=obs[i];
    }
    return (sum==0?false:true);
}

// SIT FILE
int read_siteinfo(struct Station* SIT){
    int lfound;
    char* line;
    char* tmpstr;
    line = calloc(LEN_STRING+1, sizeof(char));
    tmpstr = calloc(9, sizeof(char));
    //map<string, string>::iterator itr;
    FILE *in;
    /// gnss.cfg part
    if ((in=fopen(DLY.mTable.stacoo, "r"))==NULL){
        printf("file = %s,can't accsss site file", DLY.mTable.stacoo);
        exit(1);
    }
    memset(SIT->x, 0, sizeof(double) * 3);
    memset(SIT->qx, 0, sizeof(double) * 3);
    memset(SIT->dx0, 0, sizeof(double) * 3);
    lfound = 0;
    strcpy(tmpstr,SIT->name);
    strcat(tmpstr, "_POS");
    while (fgets(line, LEN_STRING, in))
    {
        if (strstr(line, tmpstr))
        {
            lfound = 1;
            break;
        }
    }
    if (!lfound)
    {
        printf("staname = %s,file = %s,station is not exist in the site file", SIT->name, DLY.mTable.stacoo);
        fclose(in);
        return 0;
    }
    memset(tmpstr,0,sizeof(char)*strlen(tmpstr));

    sscanf(line, "%*s%lf%lf%lf", SIT->x, SIT->x + 1, SIT->x + 2);
    fgets(line, LEN_STRING, in);
    strcpy(tmpstr,SIT->name); strcat(tmpstr, "_SIG");
    if (strstr(line, tmpstr))
    {
        sscanf(line, "%*s%lf%lf%lf%*54c%lf%lf%lf", SIT->dx0, SIT->dx0 + 1,
               SIT->dx0 + 2, SIT->qx, SIT->qx + 1, SIT->qx + 2);
    }
    else
    {
        printf("staname = %s,file = %s,site file format error", SIT->name, DLY.mTable.stacoo);
        return 0;
    }
    memset(tmpstr,0,sizeof(char)*strlen(tmpstr));

    fgets(line, LEN_STRING, in);
    strcpy(tmpstr,SIT->name); strcat(tmpstr, "_ENU");
    if (strstr(line, tmpstr))
    {
        sscanf(line, "%*s%lf%lf%lf", SIT->enu0, SIT->enu0 + 1, SIT->enu0 + 2);
        strncpy(SIT->rectyp,line+58, 20);
        strncpy(SIT->anttyp,line+85, 20);
        if (!strstr(SIT->anttyp, "NONE") && len_trim(SIT->anttyp) < 13){
            memset(SIT->anttyp, 0, sizeof(char)*20);
            strncpy(SIT->anttyp,line+0,16);
            strcat(SIT->anttyp,"NONE");
        }
    }
    else
    {
        printf("staname = %s,file = %s,site file format error", SIT->name, DLY.mTable.stacoo);
        fclose(in);
        return 0;
    }
    fclose(in);
    if (SIT->x[0] == 0 || SIT->x[1] == 0 || SIT->x[2] == 0)
    {
        //printf("staname = %s,file = %s,no coordinate information for station in site file\n", SIT->name, DLY.mTable.stacoo);
    }
    free(line);
    free(tmpstr);
    return 1;
}

// OBS FILE
void fillobs(char* line, int nobs, int itemlen, double ver) {
    int OFFSET = 0, len, i;
    char tmp[256]={0};
    if (ver > 3.0)
        OFFSET = 3;
    len = len_trim(line);
    for (i = len;i < itemlen * nobs + OFFSET;i++)
        line[i] = ' ';
    line[itemlen * nobs + OFFSET] = '\0';
    for (i = 0;i < nobs;i++)
    {
        memset(tmp, 0, sizeof(char) * 256);
        substringEx(tmp, line + OFFSET + i * itemlen, 0, itemlen - 2); // last is signal strength
        if (len_trim(tmp) == 0)
        {
            line[itemlen * i + OFFSET + 1] = '0';
        }
    }
}

// EPH FILE
void filleph(char* line, double ver) {
    int i, len, cpre = 4;
    char tmp[128];
    if (ver < 3.0)
        cpre = 3;
    len = len_trim(line);
    for (i = len;i < cpre + 19 * 4;i++)
    {
        line[i] = ' ';
    }
    line[cpre + 19 * 4] = '\0';
    for (i = 0; i < 4; i++)
    {
        substringEx(tmp, line + cpre + 19 * i, 0, 19);
        if (len_trim(tmp) == 0)
        {
            line[cpre + 19 * i + 1] = '0';
        }
    }
}